#ifndef __SOC_ADC_BASE_H__
#define __SOC_ADC_BASE_H__

#include <functional>
#include <stdint.h>
#include "soc/iperipheral.h"
#include "soc/soc_comm_def.h"
#include "interface/if_soc_adc.h"

#ifdef HAL_ADC_MODULE_ENABLED

/// @brief SOC_Adc
///   1、多通道采集，在轮询模式和中断模式下，意义不大，通过重新配置通道更方便
///      所以多通道采集一般配合DMA使用
class SOC_Adc : public IF_SOC_Adc
{
public:
    explicit SOC_Adc(AdcDevId id = AdcDevId::None,  void *handle = nullptr);
    virtual ~SOC_Adc();

public:
    //校准
    void Calib();
    
    void StartAdcAsync();
    int GetValueAsync();

    //单通道阻塞读取 [轮询模式,最简单的读取]
    int GetValue(int ch);
    
    //轮询模式启动 [多个通道]
    void StartAllAdcPoll(uint16_t *buffer, int size);
    
    //
    void StopAdc();

    void StartAdc_IT(int ch);
    void StopAdc_IT();

    //DMA 在多次采集，求平均时才有意义 [因为STM32的DMA，中断不能屏蔽，这样在1次采样下，会频繁中断，太耗CPU]
    void StartAdc_DMA(int chCount);
    void StartAdc_DMA_NS(int chCount, int sampleCount);
    void StopAdc_DMA();
    int GetDMAValue(int index);
    uint16_t *GetDMABuffer();

public:
    void SetAdcConvertOverCallBack(const IF_SOC_Adc::ADC_CONVERT_OVER_IRQ_FUNC &&func);
    void Raise_ConvertOver_IRQ();

private:
    void ConfigAdcCh(void *handle, int ch);
    void CalibAdcImpl();

private:
    uint8_t m_chCount = 0;
    int m_sampleCount = 1;
    uint16_t *m_buffer_DMA = nullptr;

    IF_SOC_Adc::ADC_CONVERT_OVER_IRQ_FUNC m_convertOverIrqFunc = nullptr;
    uint8_t m_lastConfigCh = -1;
};

#endif 

#endif // __SOC_ADC_BASE_H__
